查看原文
其他

【第2188期】使用JavaScript跟踪Web应用程序的性能

飘飘 前端早读课 2021-04-22

前言

了解用户在浏览你的应用程序时是否遇到困难是很重要的。今日前端早读课文章由@飘飘翻译投稿分享。

正文从这开始~~

I. 简介✌️

今年9月,有机会加入Forest Admin公司,这家公司负责构建任何 web 应用程序的管理面板,并提供一个基于 api 的框架来实现所有特定的业务流程。

我的第一个任务是实现对应用加载时间的监控,以及对客户在管理后台提出的请求时间的监控。

这种功能的目的是能够针对一些用户遇到加载时间较长的项目,以优化其界面的配置。这样可以让应用上的导航和交互更加流畅,从而提高用户体验。

要做到这一点,第一步就是要找出我们将如何实现这样的功能。根据所使用的开发框架,可能已经存在附加组件。例如,如果你是React开发者,react-addons-perf应该可以让你做你想要的跟踪。在Forest Admin,我们使用Ember.js,没有类似于React的插件。

因此,我们将使用Performance API,根据文档,它应该允许我们做我们想要做的事情。

高分辨率时间标准定义了一个支持应用程序内客户端延迟测量的 Performance 接口。性能接口被认为是高分辨率,因为它们精确到千分之一毫秒(受硬件或软件限制)。

二、性能API 🚀

Performance API受益于多种多样的方法。在我们的例子中,我们只需要5个不同的方法。

  • mark

  • measure

  • getEntriesByType

  • clearMarks / clearMeasures

1. mark

mark方法允许我们放置一个时间标记。它只需要一个参数(字符串)来引用标记,并且不返回任何结果。这将允许我们在稍后计算时间。

  1. performance.mark('start');

2. measure

measure方法允许测量两个标记之间的时间差。它接受3个参数:创建的measure方法的名称(字符串),开始标记(字符串),结束标记(字符串)。该方法返回一个具有计算两个标记之间差值的duration属性的对象。

  1. async function timeDuration() {

  2. performance.mark('start');

  3. await new Promise(resolve => setTimeout(resolve, 100))

  4. performance.mark('end');


  5. return performance.measure('time', 'start', 'end').duration;

  6. }


  7. timeDuration().then((result) => console.log(result));

  8. // output: 100

3. getEntriesByType

getEntriesByType方法允许访问创建特定类型的所有实体。它返回一个对象数组,并将输入的类型(字符串)作为参数,其中包括:frame、navigation、resource、mark、measure、paint & longtask。别担心,我们只需要mark和measure,😉。

  1. performance.getEntriesByType('measure');

  2. // output: return an Array of Object containing all the measure

4. clearMarks / clearMeasures

clearMarks / clearMeasures方法用于从浏览器缓存中删除之前添加的markers和measures。这些方法不返回任何结果,也不接受任何参数。

  1. performance.mark('start');

  2. performance.mark('end');

  3. performance.measure('time_duration', 'start', 'end');


  4. console.log(performance.getEntriesByType('mark').length);

  5. // output: 2

  6. console.log(performance.getEntriesByType('measure').length);

  7. // output: 1


  8. performance.clearMarks();

  9. performance.clearMeasures();

  10. console.log(performance.getEntriesByType('mark').length);

  11. // output: 0

  12. console.log(performance.getEntriesByType('measure').length);

  13. // output: 0

III. 让我们深入了解一下代码🌲。

现在我们知道了实现功能的方法,我们需要将其整合到现有的代码中。我们有两种可能:创建markers并直接在所需代码的地方执行测量,或者创建一个服务(timetracker.js)并将其注入代码中。为了清晰起见,我们将选择第二种方案。

  1. export default Service.extend({


  2. clearMarks() {

  3. performance.clearMarks();

  4. },


  5. startInterface() {

  6. performance.mark('timing_interface_start');

  7. },


  8. stopInterface() {

  9. performance.mark('timing_interface_stop');

  10. },


  11. measureTimingInterface() {

  12. return performance.measure(

  13. 'timing_interface',

  14. 'timing_interface_start',

  15. 'timing_interface_stop'

  16. );

  17. },


  18. startRequest() {

  19. performance.mark('timing_request_start');

  20. },


  21. stopRequest() {

  22. performance.mark('timing_request_stop');

  23. },


  24. measureTimingRequest() {

  25. return performance.measure(

  26. 'timing_request',

  27. 'timing_request_start',

  28. 'timing_request_stop'

  29. );

  30. },

  31. });

很简单,不是吗?现在我们需要在代码中的位置调用服务函数,以便我们跟踪请求和接口的加载时间。

对于接口来说,必须在页面加载开始的时候调用timinginterfacestart标记。路由的模型方法是第一个被调用的,我们会选择把它放在这里。还可以使用组件或最初调用的任何其他函数的生命周期上的方法。

但是,必须注意标记的位置。如果标记的位置不对,后续的测量将不准确。

  1. import { inject as service } from '@ember/service';


  2. export default class RouteExample extends Route {

  3. @service timeTracker;


  4. model() {

  5. this.timeTracker.startInterface();

  6. // do something

  7. }

  8. }

对于timinginterfacestop标记,它必须在应用程序渲染刚刚结束时被调用。由于这涉及到几个组件的渲染,一个合理的方法是使用这些组件的生命周期上的方法。didRender ember组件方法似乎是一个很好的候选方法。

然后是测量接口的总加载时间。可以把它放在timinginterfacestop标记之后或者其他任何需要的位置。

  1. import { inject as service } from '@ember/service';


  2. export default class RenderingTracker extends Component {

  3. @service timeTracker;


  4. didRender() {

  5. this.timeTracker.stopInterface();

  6. }

  7. stopInterfaceTracking() {

  8. return this.timeTracker.measureTimingInterface()

  9. }

  10. }

为了计算用户服务器上的请求时间,只需将负责请求用户服务器的函数周围加上标记timingrequeststart和timingrequeststop即可。

然后我们就可以通过调用我们服务的measureTimingRequest()方法来测量请求的时间。

  1. import { inject as service } from '@ember/service';


  2. export default class RouteExample extends Route {

  3. @service timeTracker;


  4. model() {

  5. this.timeTracker.startInterface();

  6. // do something

  7. }


  8. async function fetchData(params) {

  9. //do something


  10. this.timeTracker.startRequest();

  11. const records = await fetchRecords(params);

  12. this.timingTracker.stopRequest();


  13. const timingRequest = this.timingTracker.measureTimingRequest()

  14. // do something else


  15. }

  16. }

Conclusion 🥳

希望你喜欢这篇文章。欢迎提出任何意见,我将很乐意讨论。我想借此机会感谢森林管理公司的人,他们帮助我实现了这个功能。

还有其他的可能性来实现这个功能。我选择向你展示对我来说更有意义的方式。API性能是一个强大的工具,可以了解你的应用程序的性能。了解用户在浏览你的应用程序时是否遇到困难是很重要的。事实上,它可以让你主动地针对问题来解决问题,改善用户体验。

下一步可以整合一封电子邮件给加载时间超过阈值的用户,以指导他们优化某些参数。

关于本文 译者:@飘飘 作者:@Louis Clisson 原文:https://medium.com/forest-admin/track-performance-of-your-web-application-with-javascript-c27cb91a2368


为你推荐


【第2139期】Web应用程序如何工作:客户端开发和部署


【第1174期】Crooked Style Sheets:只用CSS实现网页跟踪、分析


欢迎自荐投稿,前端早读课等你来

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存